/*
 * TowerYellowThree.cs
 *
 * Created on December 15, 2007, 1:37 PM
 *
 * Copyright (C) 2007-2008  Hylke van der Schaaf
 * Copyright (C) 2010       Mathijs Miermans
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, in version 3 of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

using System;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;

using HexTD.hex;
using HexTD.sprite;
using HexTD.util;

namespace HexTD.tower
{
	public class TowerYellowThree : TowerBase
	{
		public static int price = 2000000;
		public static int damage = 20000000;
		public static float range = 8f;

		private int fireAt = -1;
		private float enemyX = 0;
		private float enemyY = 0;
		private EnemySprite enemy;
		private COLOR damageColor = COLOR.YELLOW;
		private int charge = 0;
		private int chargeMax = 81;

		private Color transColor;
		private Brush[] beam1Strokes;
		private Brush[] beam2Strokes;
		private Brush beam1Stroke;
		private Brush beam2Stroke;
		private Color beam1Color;
		private Color beam2Color;
		private Shape[] pies;
		private Color line2Color;

		/** Creates a new instance of TowerYellowThree */
		public TowerYellowThree(Context context, Hex hex)
			: base(TowerFactory.type.yellowThree, price, damage, range)
		{
			this.lineColor = Color.FromArgb(0xFF, 220, 220, 0);
			this.line2Color = Color.FromArgb(0xFF, 110, 110, 0);
			this.transColor = Color.FromArgb(100, this.lineColor.R, this.lineColor.G, this.lineColor.B);
			this.beam1Color = Color.FromArgb(100, this.lineColor.R, this.lineColor.G, this.lineColor.B);
			this.beam2Color = Color.FromArgb(0xFF, 255, 255, 128);
			this.doInit(context, hex);
		}

		public bool aquireTarget()
		{
			int enemyNr = this.findEnemy(this.fireAt, false);
			this.fireAt = enemyNr;
			if (enemyNr >= 0)
			{
				this.enemy = this.context.enemies[enemyNr];
				this.enemyX = enemy.getX();
				this.enemyY = enemy.getY();
				return true;
			}
			return false;
		}

		public override void doTick(int gameTime)
		{
			if (this.fireAt == -1 || this.charge == 0)
			{
				if (this.charge > 0)
				{
					this.charge--;
				}
				if (this.aquireTarget())
				{
					this.charge += 2;
				}
			}

			if (this.fireAt != -1)
			{
				// Still a valid target?
				if (this.enemy.validTarget())
				{
					this.charge += 2;
					if (this.charge >= this.chargeMax - 1)
					{
						enemy.doDamage(this.damageCurrent, this.damageColor);
						this.charge = 0;
					}
					else
					{
						this.beam1Stroke = this.beam1Strokes[this.charge - 1];
						this.beam2Stroke = this.beam2Strokes[this.charge - 1];
					}
				}
				else
				{
					this.charge = (int)Math.Floor(this.charge * 0.9f);
					this.fireAt = -1;
				}
			}
		}

		public override string getStatusString()
		{
			string retString = "";
			retString += "<h1>Yellow Tower 3</h1>" +
					"<p>" +
					"<b>Level:</b> " + (1 + this.level) + "<br>\n" +
					"<b>Damage:</b> " + this.damageText + "<br>\n" +
					"<b>Range:</b> " + this.rangeText + "<br>" +
					"</p>\n";
			return retString;
		}

		public override string getInfoString()
		{
			string retString = "";
			retString += "<h1>Yellow Tower 3</h1>" +
					"<p>" +
					"Like yellow tower 2, but if the target is destroyed before firing, only 10% of the charge is lost. " +
					"When there is no target available the charge will gradually drop to zero." +
					"<br>Strong against yellow enemies, very weak against blue enemies." +
					"</p>" +
					"<p>" +
					"<b>Price:</b> " + price + "<br>" +
					"<b>Damage:</b> " + this.damageCurrent + "<br>" +
					"<b>Range:</b> " + rangeCurrent + "<br>" +
					"<b>Refire rate:</b> 0.5/s" +
					"</p>";
			return retString;
		}

		protected override void generateShapes()
		{
#if PORT
			float width = this.context.hexPaintWidth;
			float scale2 = 0.5f * this.paintScale;
			int shapeCount = 8;

			this.shapes = new Shape[shapeCount];

			float[,] points2 = Geometry.createPolyCoords(this.paintScale);
			GeneralPath polyHex = Geometry.coordsToGeneralPath(points2, true);

			Area tower = new Area(polyHex);

			float[,] points1 = Geometry.createPolyCoords(scale2);
			polyHex = Geometry.coordsToGeneralPath(points1, true);
			Area tempArea = new Area(polyHex);

			tower.subtract(tempArea);
			this.shapes[0] = tower;
			this.shapes[1] = new Ellipse.Float(-1.0f * this.context.strokeScale, -1.0f * this.context.strokeScale, 2.0f * this.context.strokeScale, 2.0f * this.context.strokeScale);
			this.shapes[2] = new LineSegment.Float(points1[0, 0], points1[0, 1], points2[0, 0], points2[0, 1]);
			this.shapes[3] = new LineSegment.Float(points1[3, 0], points1[3, 1], points2[3, 0], points2[3, 1]);

			this.shapes[4] = new LineSegment.Float(0, 0, points1[1, 0], points1[1, 1]);
			this.shapes[5] = new LineSegment.Float(0, 0, points1[2, 0], points1[2, 1]);
			this.shapes[6] = new LineSegment.Float(0, 0, points1[4, 0], points1[4, 1]);
			this.shapes[7] = new LineSegment.Float(0, 0, points1[5, 0], points1[5, 1]);

			this.shapeAction = new int[shapeCount];
			this.shapeAction[0] = 2;

			this.shapeColor = new Color[shapeCount];
			this.shapeColor[0] = this.lineColor;

			this.strokes = new Brush[shapeCount];
			this.strokes[0] = new Brush(2.0f * this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);

			float max = this.chargeMax;
			this.pies = new Shape[this.chargeMax + 1];
			for (int i = 0; i < this.pies.Length; i++)
			{
				this.pies[i] = new Arc2D.Float(-scale2, -scale2, scale2 * 2, scale2 * 2, 0, 360f * i / (max - 1), Arc2D.PIE);
			}

			this.beam1Strokes = new Brush[this.chargeMax];
			this.beam2Strokes = new Brush[this.chargeMax];
			for (int i = 0; i < this.chargeMax; i++)
			{
				this.beam1Strokes[i] = new Brush(6.0f * (float)i / max * this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
				this.beam2Strokes[i] = new Brush(3.0f * (float)i / max * this.context.strokeScale, Brush.CAP_ROUND, Brush.JOIN_BEVEL);
			}
#endif
		}

		public override void paint(Canvas g2, int gameTime)
		{
#if PORT
			Brush defaultStroke = g2.getStroke();
			RotateTransform saveXform = g2.getTransform();

			g2.transform(atTranslate);

			g2.setColor(this.lineColor);
			g2.setStroke(this.strokes[0]);
			g2.fill(this.pies[this.charge]);

			g2.setColor(this.line2Color);
			g2.fill(this.shapes[0]);

			g2.setColor(this.lineColor);
			g2.draw(this.shapes[0]);
			g2.draw(this.shapes[1]);
			g2.draw(this.shapes[2]);
			g2.draw(this.shapes[3]);
			g2.draw(this.shapes[4]);
			g2.draw(this.shapes[5]);
			g2.draw(this.shapes[6]);
			g2.draw(this.shapes[7]);

			g2.setFont(this.levelFont);
			g2.drawString("" + (this.level + 1), this.levelLocation[0], this.levelLocation[1]);

			if (this.selected)
			{
				g2.setColor(this.rangeColor);
				g2.draw(this.rangeCircle);
			}

			g2.setTransform(saveXform);
			g2.setStroke(defaultStroke);
#endif
		}

		public override void paintEffects(Canvas g2, int gameTime)
		{
#if PORT
			Brush defaultStroke = g2.getStroke();

			if (this.fireAt > -1 && this.charge > 0)
			{
				float ex = this.enemy.getPaintX();
				float ey = this.enemy.getPaintY();
				g2.setColor(this.beam1Color);
				g2.setStroke(this.beam1Stroke);
				g2.draw(new LineSegment.Float(this.xPaint, this.yPaint, ex, ey));
				g2.setColor(this.beam2Color);
				g2.setStroke(this.beam2Stroke);
				g2.draw(new LineSegment.Float(this.xPaint, this.yPaint, ex, ey));
			}

			g2.setStroke(defaultStroke);
#endif
		}
	}
}